/*******************************************************************************
 *                           TacticaHimura.java                                *
 *                              JavaCup 2007                                   *
 *                           Csar Himura Elric                                *
 *******************************************************************************/

package futbol.tacticas.concursantes2007.LegionXEquestris;

import java.awt.Color;
import java.awt.Point;

import java.util.Vector;

import futbol.General;
import futbol.tacticas.Comando;
import futbol.tacticas.SituacionJugadores;
import futbol.tacticas.ComandoGolpearBola;
import futbol.tacticas.ComandoIrA;
import futbol.tacticas.ComandoPase;
import futbol.tacticas.ComandoTiroAPuerta;
import futbol.tacticas.concursantes.Tactica;
        
/**
 *
 *@author Csar Himura Elric
 */
public class TacticaHimura implements Tactica
{
    private int nValores[][] =
    {
        {-149,0,5},  // Portero 1[0]
        {-105,-70,6},  // Defensa 1[1]
        {-120,-25,6},  // Defensa 2[2]
        {-120,25,6},  // Defensa 3[3]
        {-105,70,6},  // Defensa 4[4]
        {-40,70,6},  // Medio Derecho[5]
        {-40,-70,7},  // Medio Izquierdo[6]
        {-62,-1,6},  // Medio Contension[7]
        {100,-30,7},  // Delantero 1[8]
        {50,-4,7},  // Medio Enganche[9]
        {100,30,7}  // Delantero 2[10]
    };
    
    public Color getColor1()
    {
        return Color.red;
    }
    
    public Color getColor2()
    {
        return Color.white;
    }
    
    public Color getColorNumero()
    {
        return Color.black;
    }
    
    public String getNombre()
    {
        return "Legin X Equestris";
    }
    
    public int getXInicial(int n) 
    {
        return nValores[n][0];
    }

    public int getYInicial(int n)
    {
        return nValores[n][1];
    }

    public int getFuerza(int n) 
    {
        return nValores[n][2];
    }

    public Vector<Comando> getComandos(SituacionJugadores sj) 
    {
        Vector<Comando> com = new Vector();
        
        for (int n = 0; n < 11; n++)
            com.add(new ComandoIrA(n,nValores[n][0],nValores[n][1]));
        
        int nJug = sj.getMasCercanoDeBola();
        Point bola = sj.getBola();
        com.add(new ComandoIrA(nJug, bola.getX(), bola.getY()));

        int yPortero = (int)(bola.getY()/2);
        int xPortero = getXInicial(0);
        
        if(sj.getMasCercanoDeBola() != 0)
        {
            if(bola.getY() < -20) yPortero = -25;
            if(bola.getY() > 20) yPortero = 25;

            if(bola.getX() > -50) xPortero = -146;
            if(bola.getX() < -50) xPortero = -154;
            com.add(new ComandoIrA(0, xPortero, yPortero));
        }
        
        Point[] contras = sj.getContrario();
        for(int index = 0; index < contras.length; index++)
        {
            if(contras[index].getX() <= -65)
            {
                int nJ = sj.getMiJugadorMasCerca(contras[index].getX(), contras[index].getY());
                
                if(nJ != 0)
                    setMarcaje(sj, com, nJ, index);
            }
        }

        if(sj.getMasCercanoDeBola() != 7)
        {
            switch(getCuadrante(sj.getBola()))
            {
                case 1: com.add(new ComandoIrA(7, -14, 52));
                        break;
                case 2: com.add(new ComandoIrA(7, -64, 40));
                        break;
                case 3: com.add(new ComandoIrA(7, -64, -40));
                        break;
                case 4: com.add(new ComandoIrA(7, 0, -30));
                        break;
            }
        }
        
        int xMedioDer = getXInicial(5);
        
        if(sj.getMasCercanoDeBola() != 5)
        {
            xMedioDer = ((int)(bola.getX()/2)) >= 0 ? 50 : -50;
            com.add(new ComandoIrA(5, xMedioDer, nValores[5][1]));
        }
        
        int xMedioIzq = getXInicial(6);
        
        if(sj.getMasCercanoDeBola() != 6)
        {
            xMedioIzq = ((int)(bola.getX()/2)) >= 0 ? 70 : -10;
            com.add(new ComandoIrA(6, xMedioIzq, nValores[6][1]));
        }
        
        int yMedioEng = getYInicial(9);
        
        if(sj.getMasCercanoDeBola() != 9)
        {
            yMedioEng = ((int)(bola.getY()/2)) >= 0 ? 30 : -30;
            com.add(new ComandoIrA(9, getXInicial(9), yMedioEng));
        }
        
        for(int num = 8; num < 11; num+=2)
        {
            if(sj.getMasCercanoDeBola() != num)
                desmarcaDelantero(sj, num, com);
        }
        
        SistemaPases(sj, com);
        
        for(int n = 8; n <= 11; n++)
        {
            SistemaDisparo(sj, com, n);
        }
        
        return com;
    }
    
    private void desmarcaDelantero(SituacionJugadores sj, int numPlayer, Vector<Comando> com)
    {
        Point[] X = sj.getMisJugadores();
        Point[] C = sj.getContrario();
        
        int nJC = -1;
        
        if(X[8].getX() < 0)
        {
            nValores[8][0] = 100;
            nValores[8][1] = -30;
        }
        
        if(X[10].getX() < 0)
        {
            nValores[10][0] = 100;
            nValores[10][1] = 30;
        }
        
        if(X[numPlayer].getX() == this.getXInicial(numPlayer) && X[numPlayer].getY() == this.getYInicial(numPlayer))
        {
            nJC = sj.getContrarioMasCerca(numPlayer);
            if(General.getDistancia(X[numPlayer].getX(), X[numPlayer].getY(), C[nJC].getX(), C[nJC].getY())< 14)
            {
                if(X[numPlayer].getX() < C[nJC].getX())
                {
                    
                }
                else
                {
                    if(X[numPlayer].getX() > C[nJC].getX())
                    {
                        intercambioPosicion(numPlayer);
                        com.add(new ComandoIrA(numPlayer, this.getXInicial(numPlayer), this.getYInicial(numPlayer)));
                    }
                }
            }
        }
    }
    
    private void intercambioPosicion(int j1)
    {
        int jAux = (j1 == 10) ? 8 : 10;
        
        if(this.getYInicial(j1) > 0)
        {
            if(nValores[jAux][0] != 123)
            {
                nValores[j1][0] = 123;
                nValores[j1][1] = 0;
            }
        }
        else
        {
            if(this.getYInicial(j1) < 0)
            {
                if(nValores[jAux][0] != 83)
                {
                    nValores[j1][0] = 83;
                    nValores[j1][1] = 0;
                }
            }
            else
            {
                if(this.getYInicial(j1) == 0 && this.getXInicial(j1) >= 120)
                {
                    if(nValores[jAux][1] != -30)
                    {
                        nValores[j1][0] = 100;
                        nValores[j1][1] = -30;
                    }
                }
                else
                {
                    if(this.getYInicial(j1) == 0 && this.getXInicial(j1) < 120)
                    {
                        if(nValores[jAux][1] != 30)
                        {
                            nValores[j1][0] = 100;
                            nValores[j1][1] = 30;
                        }
                    }
                }
            }
        }
    }
    
    private void SistemaDisparo(SituacionJugadores sj, Vector<Comando> com, int n)
    {
        if(sj.getContrario()[0].getY() >= 0)
            com.add(new ComandoTiroAPuerta(n, -10));
        else
            com.add(new ComandoTiroAPuerta(n, 10));
    }
    
    private void setMarcaje(SituacionJugadores sj, Vector<Comando> com, int nJ, int nJC)
    {
        Point[] equipo = sj.getMisJugadores();
        Point[] contras = sj.getContrario();
        
        double[] coor = new double[2];
        
        if(sj.getMasCercanoDeBola() != nJ)
        {
            if(contras[nJC].getX() < -65)
            {
                if(General.getDistancia(equipo[nJ].getX(), equipo[nJ].getY(),contras[nJC].getX(),contras[nJC].getY()) < 30)
                {
                    coor = getMarcaje(contras[nJC].getX(), contras[nJC].getY(), sj.getBola().getX(), sj.getBola().getY());
                    com.add(new ComandoIrA(nJ, contras[nJC].getX() + coor[0], contras[nJC].getY() + coor[1]));
                }
            }
        }
    }
    
    private double[] getMarcaje(double xC, double yC, double xB, double yB)
    {
        double[] xy = new double[2];
        
        boolean upDown = false;
        boolean leftRight = false;
        
        if((yC - 10) > yB && (yC + 10) < yB)
            upDown = true;
        if((xC - 10) > xB && (xC + 10) < xB)
            leftRight = true;
        
        switch(getCuadranteBola_Jugador(xC, yC, xB, yB))
        {
            case 1: if(leftRight)
                    {
                        xy[0] = 10;
                        xy[1] = 0;
                    }
                    else
                    {
                        if(upDown)
                        {
                            xy[0] = 0;
                            xy[1] = 10;
                        }
                        else
                        {
                            xy[0] = 10;
                            xy[1] = 10;
                        }
                    }
            break;
            case 2: if(leftRight)
                    {
                        xy[0] = -10;
                        xy[1] = 0;
                    }
                    else
                    {
                        if(upDown)
                        {
                            xy[0] = 0;
                            xy[1] = 10;
                        }
                        else
                        {
                            xy[0] = -10;
                            xy[1] = 10;
                        }
                    }
            break;
            case 3: if(leftRight)
                    {
                        xy[0] = -10;
                        xy[1] = 0;
                    }
                    else
                    {
                        if(upDown)
                        {
                            xy[0] = 0;
                            xy[1] = -10;
                        }
                        else
                        {
                            xy[0] = -10;
                            xy[1] = -10;
                        }
                    }
            break;
            case 4: if(leftRight)
                    {
                        xy[0] = 10;
                        xy[1] = 0;
                    }
                    else
                    {
                        if(upDown)
                        {
                            xy[0] = 0;
                            xy[1] = -10;
                        }
                        else
                        {
                            xy[0] = 10;
                            xy[1] = -10;
                        }
                    }
            break;
        }
        
        return xy;
    }
    
    private int getCuadranteBola_Jugador(double xC, double yC, double xB, double yB)
    {
        if(xB > xC && yB > yC)
            return 1;
        if(xB < xC && yB > yC)
            return 2;
        if(xB < xC && yB < yC)
            return 3;
        if(xB > xC && yB < yC)
            return 4;
        
        return 0;
    }
    
    private int getCuadrante(Point bola)
    {
        if(bola.getX() > 0 && bola.getY() > 0)
            return 1;
        if(bola.getX() < 0 && bola.getY() > 0)
            return 2;
        if(bola.getX() < 0 && bola.getY() < 0)
            return 3;
        if(bola.getX() > 0 && bola.getY() < 0)
            return 4;
        
        return 0;
    }
    
    private void SistemaPases(SituacionJugadores sj, Vector<Comando> com)
    {
        Point[] j = sj.getMisJugadores();
         
        for(int index = 0; index < 8; index++)
        {   
            if (General.getDistancia(sj.getBola().getX(), sj.getBola().getY(), j[index].getX(), j[index].getY()) < 10)
            { 
                switch(index)
                {
                    case 0: if(sj.getBola().getY() <= 0)
                            {
                                if(!evaluaReceptor(sj, index, 1))
                                {
                                    com.add(new ComandoPase(index, 1));
                                }
                                else
                                {
                                    if(!evaluaReceptor(sj, index, 2))
                                    {
                                        com.add(new ComandoPase(index, 2));
                                    }
                                    else
                                    {
                                        com.add(new ComandoGolpearBola(index,0,-118));
                                    }
                                }
                             }
                             else
                             {
                                    if(!evaluaReceptor(sj, index, 4))
                                    {
                                        com.add(new ComandoPase(index, 4));
                                    }
                                    else
                                    {
                                        if(!evaluaReceptor(sj, index, 3))
                                        {
                                            com.add(new ComandoPase(index, 3));
                                        }
                                        else
                                        {
                                            com.add(new ComandoGolpearBola(index,0,118));
                                        }
                                    }
                              }
                    break;
                    case 1: if(!evaluaReceptor(sj, index, 6))
                            {
                                com.add(new ComandoPase(index, 6));
                            }
                            else
                            {
                                if(!evaluaReceptor(sj, index, 7))
                                {
                                    com.add(new ComandoPase(index, 7));
                                }
                                else
                                {
                                    if(!evaluaReceptor(sj, index, 5))
                                    {
                                        com.add(new ComandoPase(index, 5));
                                    }
                                    else
                                    {
                                        com.add(new ComandoGolpearBola(index,70,0));
                                    }
                                }
                            }
                    break;
                    case 2: if(!evaluaReceptor(sj, index, 6))
                            {
                                com.add(new ComandoPase(index, 6));
                            }
                            else
                            {
                                if(!evaluaReceptor(sj, index, 7))
                                {
                                    com.add(new ComandoPase(index, 7));
                                }
                                else
                                {
                                    if(!evaluaReceptor(sj, index, 5))
                                    {
                                        com.add(new ComandoPase(index, 5));
                                    }
                                    else
                                    {
                                        com.add(new ComandoGolpearBola(index,0,-118));
                                    }
                                }
                            }
                    break;
                    case 3: if(!evaluaReceptor(sj, index, 5))
                            {
                                com.add(new ComandoPase(index, 5));
                            }
                            else
                            {
                                if(!evaluaReceptor(sj, index, 7))
                                {
                                    com.add(new ComandoPase(index, 7));
                                }
                                else
                                {
                                    if(!evaluaReceptor(sj, index, 6))
                                    {
                                        com.add(new ComandoPase(index, 6));
                                    }
                                    else
                                    {
                                        com.add(new ComandoGolpearBola(index,0,118));
                                    }
                                }
                            }
                    break;
                    case 4: if(!evaluaReceptor(sj, index, 5))
                            {
                                com.add(new ComandoPase(index, 5));
                            }
                            else
                            {
                                if(!evaluaReceptor(sj, index, 7))
                                {
                                    com.add(new ComandoPase(index, 7));
                                }
                                else
                                {
                                    if(!evaluaReceptor(sj, index, 6))
                                    {
                                        com.add(new ComandoPase(index, 6));
                                    }
                                    else
                                    {
                                        com.add(new ComandoGolpearBola(index,70,0));
                                    }
                                }
                            }
                    break;
                    case 5: if(!evaluaReceptor(sj, index, 8))
                            {
                                com.add(new ComandoPase(index, 8));
                            }
                            else
                            {
                                if(!evaluaReceptor(sj, index, 10))
                                {
                                    com.add(new ComandoPase(index, 10));
                                }
                                else
                                {
                                    if(!evaluaReceptor(sj, index, 9))
                                    {
                                        com.add(new ComandoPase(index, 9));
                                    }
                                    else
                                    {
                                        if(!evaluaReceptor(sj, index, 7))                                
                                        {
                                            com.add(new ComandoPase(index, 7));
                                        }
                                        else
                                        {
                                            com.add(new ComandoGolpearBola(index,100,0));
                                        }
                                    }
                                }
                            }
                    break;
                    case 6: if(j[index].getX() >= 64)
                            {
                                com.add(new ComandoTiroAPuerta(7, 10));
                            }
                            else
                            {
                                if(!evaluaReceptor(sj, index, 10))
                                {
                                    com.add(new ComandoPase(index, 10));
                                }
                                else
                                {
                                    if(!evaluaReceptor(sj, index, 8))
                                    {
                                        com.add(new ComandoPase(index, 8));
                                    }
                                    else
                                    {
                                        if(!evaluaReceptor(sj, index, 9))
                                        {
                                            com.add(new ComandoPase(index, 9));
                                        }
                                        else
                                        {
                                            if(!evaluaReceptor(sj, index, 7))                                
                                            {
                                                com.add(new ComandoPase(index, 7));
                                            }
                                            else
                                            {
                                                com.add(new ComandoGolpearBola(index,100,0));
                                            }
                                        }
                                    }
                                }
                            }
                    break;
                    case 7: if(sj.getBola().getY() <= 0)
                            {
                                if(!evaluaReceptor(sj, index, 6))
                                {
                                    com.add(new ComandoPase(index, 6));
                                }
                                else
                                {
                                    com.add(new ComandoGolpearBola(index, 55, -60));
                                }
                            }
                            else
                            {
                                if(!evaluaReceptor(sj, index, 5))
                                {
                                    com.add(new ComandoPase(index, 5));
                                }
                                else
                                {
                                    com.add(new ComandoGolpearBola(index, 55, 60));
                                }
                            }
                    break;
                }
            }
        }
    }
    
    private boolean evaluaReceptor(SituacionJugadores sj, int index, int nRec)
    {
        Point[] j = sj.getMisJugadores();
        Point[] c = sj.getContrario();
         
        double[] recta;
        double[] circunferencia;
        
        final double r = 16;
        
        int contra = -1;
        
        recta = getRecta(j[index].getX(), j[index].getY(), j[nRec].getX(), j[nRec].getY());
        contra = sj.getContrarioMasCerca(nRec);
        circunferencia = getCircunferencia(c[contra].getX(), c[contra].getY(), r);
        
        return intersectaRectaCircunferencia(recta, circunferencia);
    }
    
    private double[] getDesarrollaBinomio(double a, double b)
    {
        double[] binomio = new double[3];
        
        binomio[0] = Math.pow(a, 2);
        binomio[1] = a * b * 2;
        binomio[2] = Math.pow(b, 2);
        
        return binomio;
    }
    
    private double[] getCircunferencia(double x, double y, double r)
    {
        double[] ecuacion = new double[5];
        
        x = x * -1;
        y = y * -1;
        
        double[] b = getDesarrollaBinomio(1, x);
        
        for(int index = 0; index < b.length; index++)
        {
            ecuacion[index] = b[index];
        }
        
        b = getDesarrollaBinomio(1, y);
        
        ecuacion[4] = ecuacion[2] + b[2] + Math.pow(r, 2) * -1;
        ecuacion[2] = b[0];
        ecuacion[3] = b[1]; 
        
        return ecuacion;
    }
    
    private double[] getRecta(double x1, double y1, double x2, double y2)
    {
        double[] ecuacion = new double[3];
        
        ecuacion[0] = 1;
        
        ecuacion[1] = (y1 - y2)/(x1 - x2);
        
        ecuacion[2] = ecuacion[1] * x1 + y1;
        
        return ecuacion;
    }
    
    private double[] getSolucionEcSegundoGrado(double a, double b, double c)
    {
        double[] x = new double[2];
        
        x[0] = (-1 * b + Math.sqrt((Math.pow(b, 2) - (4 * a * c))))/(2 * a);
        x[1] = (-1 * b - Math.sqrt((Math.pow(b, 2) - (4 * a * c))))/(2 * a);
        
        return x;
    }
    
    private boolean intersectaRectaCircunferencia(double[] recta, double[] circunferencia)
    {
        double[] ecuacionSimple = new double[3];
        
        double[] b = getDesarrollaBinomio(recta[1], recta[2]);
        
        ecuacionSimple[0] = circunferencia[0] + b[0];
        ecuacionSimple[1] = circunferencia[1] + b[1];
        ecuacionSimple[2] = circunferencia[4] + b[2];
        
        ecuacionSimple[1] += circunferencia[3] * recta[1];
        ecuacionSimple[2] += circunferencia[3] * recta[2];
        
        double[] x = getSolucionEcSegundoGrado(ecuacionSimple[0], ecuacionSimple[1], ecuacionSimple[2]);
        for(int index = 0; index < x.length; index++)
        {
            if(Double.isNaN(x[index]))
            {
                return false;
            }
        }
        
        return true;
    }
}